#include "Thread.hpp"
#include "BlockQueue.hpp"
#include "Task.hpp"
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <ctime>

using namespace ThreadModule;

// 这里代表BlockQueue以后不再放的是int而是Task 并且还能更方便的更改类型
using blockqueue_t = BlockQueue<Task>;

class ThreadData
{
private:
    blockqueue_t &bq;
    std::string who;
};

void PrintHello()
{
    std::cout << "hello world" << std::endl;
}

void Product(blockqueue_t &bq)
{
    // 种一颗随机数种子
    srand(time(nullptr) ^ pthread_self()); // 按位或上pthread_self会让随机数更随机
    while (true)
    {
        // 1、获取任务
        // int a = rand() % 10 + 1;
        // usleep(1234);
        // int b = rand() % 20 + 1;
        // Task t(a, b);

        // 2、把获取的任务放进blockqueue
        Task t = PrintHello;
        bq.Enqueue(t);
        // bq.Enqueue(t);
        // std::cout << "Producter : " << t.DebugToString() << std::endl;
        sleep(1);
    }
}
void Consum(blockqueue_t &bq)
{
    while (true)
    {
        // // 1、从blockqueue取出来任务
        Task t;
        bq.Pop(&t); // 利用输出型参数 取出参数
        // // 2、执行任务
        t();
        // t.Excute();
        // 打印看结果
        // std::cout << "Consumer : " << t.ResultToString() << std::endl;
        sleep(1);
    }
}

void StartComm(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq, func_t<blockqueue_t> func)
{
    // 创建线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        threads->emplace_back(func, bq, name);
        // 启动线程
        threads->back().Start();
    }
}
void StartProduct(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
{
    StartComm(threads, num, bq, Product);
}
void StartConsume(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
{
    StartComm(threads, num, bq, Consum);
}
void WaitAllThread(std::vector<Thread<blockqueue_t>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    blockqueue_t *bq = new blockqueue_t(5);
    std::vector<Thread<blockqueue_t>> threads;

    StartProduct(&threads, 1, *bq);
    StartConsume(&threads, 5, *bq);
    WaitAllThread(threads);
    return 0;
}

/*
------- 以下是使用整数来初步实现生产消费者模型，后面就要让这个模型 运行一些任务 --------------

#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include "Thread.hpp"
#include "BlockQueue.hpp"

using namespace ThreadModule;

int a = 10;
void Product(BlockQueue<int> &bq)
{
    int cnt = 1;
    while (true)
    {
        bq.Enqueue(cnt);
        std::cout << "Producter product data is : " << cnt << std::endl;
        cnt++;
        // sleep(1);
    }
}
void Consum(BlockQueue<int> &bq)
{
    while (true)
    {
        int data;
        bq.Pop(&data);
        std::cout << "Consumer consum data is : " << data << std::endl;
        sleep(1);
    }
}

void StartComm(std::vector<Thread<BlockQueue<int>>> *threads, int num, BlockQueue<int> &bq, func_t<BlockQueue<int>> func)
{
    // 创建线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        threads->emplace_back(func, bq, name);
        // 启动线程
        threads->back().Start();
    }
}
void StartProduct(std::vector<Thread<BlockQueue<int>>> *threads, int num, BlockQueue<int> &bq)
{
    StartComm(threads, num, bq, Product);
}
void StartConsume(std::vector<Thread<BlockQueue<int>>> *threads, int num, BlockQueue<int> &bq)
{
    StartComm(threads, num, bq, Consum);
}
void WaitAllThread(std::vector<Thread<BlockQueue<int>>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    BlockQueue<int> *bq = new BlockQueue<int>(5);
    std::vector<Thread<BlockQueue<int>>> threads;

    StartProduct(&threads, 1, *bq);
    StartConsume(&threads, 5, *bq);
    WaitAllThread(threads);
    return 0;
}
*/